package com.su.gulimall.auth.web;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.su.common.constant.AuthServerConstant;
import com.su.common.exception.BizCodeEnume;
import com.su.common.utils.R;
import com.su.common.vo.MemberRespVo;

import com.su.gulimall.auth.feign.RegisterFeignService;
import com.su.gulimall.auth.feign.SmsFeignService;
import com.su.gulimall.auth.util.HttpUtils;
import com.su.gulimall.auth.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Controller
public class IndexController {
    @Autowired
    SmsFeignService smsFeignService;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    RegisterFeignService registerFeignService;


    //当只负责跳转，而不用进行内容处理可以考虑配置视图映射；(webMvcConfigurer)
    //实现验证码的发送，存储redis功能
    @GetMapping("/sms/sendCode")
    @ResponseBody
    public R sendCode(String phone) {
        String redisCode = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_REDIS_PREFIX + phone);
        //当redis中，存储该手机号对应的key时，对其判断是否过期；没有存储该key,直接发送验证码，并保存在redis中
        if (!StringUtils.isEmpty(redisCode)) {
            long expiredTime = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - expiredTime < 60 * 1000) {
                //验证码的时间没有超过60秒，不予发送
                //TODO:第一，接口防刷新，严格意义上的60s
                return R.error(BizCodeEnume.SMS_CODE_EXCEPTION.getCode(), BizCodeEnume.SMS_CODE_EXCEPTION.getMsg());
            }
        }
        //第二，验证码的校验：可以使用redis临时存储
        String code = "5873" + "_" + System.currentTimeMillis();
        //redis缓存了验证码
        redisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_REDIS_PREFIX + phone, code, 10, TimeUnit.MINUTES);
        R r = smsFeignService.sendCode(phone);
        return r.ok();
    }
    //实现注册功能
    @PostMapping("/register")
    public String register(@Valid UserRegisterVo vo, BindingResult result, RedirectAttributes model) {
        //前端校验失败的返回情况
        if (result.hasErrors()) {

            Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(
                    FieldError::getField, FieldError::getDefaultMessage
            ));
            model.addFlashAttribute("errors", errors);
            //校验出错
            //用户注册->register(post)->转发/register.html(路径映射默认都是get请求)
            return "redirect:http://auth.gulimall.com/register.html";
        }
        //校验验证码是否正确,从前端获取的为code
        String code = vo.getCode();
        //从redis中进行获取
        String s = redisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_REDIS_PREFIX + vo.getPhone());
        Map<String, String> codeErrors = new HashMap<>();
        if (!StringUtils.isEmpty(s)) {
            if (code.equals(s.split("_")[0])) {
                //验证码校验成功，删除缓存中的验证码，下次请求需要重新发送验证码;令牌机制
                redisTemplate.delete(AuthServerConstant.SMS_CODE_REDIS_PREFIX + vo.getPhone());
                //真正的注册服务实现，将数据写入数据库，需要远程调用
                R r = registerFeignService.register(vo);
                if (r.getCode() == 0) {
                    //注册成功回到网站的首页
                    return "redirect:http://auth.gulimall.com/login.html";
                }
                if (r.getCode() != 0) {
                    //当状态码出现异常
                    Map<String, String> errors = new HashMap<>();
                    //TODO:手机号应当是唯一值，这个R返回error信息
                    errors.put("msg", "手机号已存在");
                    model.addFlashAttribute("errors", errors);
                    return "redirect:http://auth.gulimall.com/register.html";
                }
            } else {
                //验证码对比不正确，即验证码出现错误
                codeErrors.put("code", "请检查验证码是否输入正确");
                model.addFlashAttribute("errors", codeErrors);
                return "redirect:http://auth.gulimall.com/register.html";
            }
        }
        else {
            //缓存中没有该手机号对应的验证码信息，即验证码校验出错
            codeErrors.put("code", "请检查手机号是否输入正确");
            model.addFlashAttribute("errors", codeErrors);
            return "redirect:http://auth.gulimall.com/register.html";
        }
        return "redirect:http://auth.gulimall.com/register.html";
    }
    //普通登录
    @PostMapping("/login")
     public String login(LoginVo vo,RedirectAttributes redirectAttributes,HttpSession session)
    {
        //远程登录验证
        R r = registerFeignService.login(vo);
        if(r.getCode()!=0)
        {
            Map<String,String> errors=new HashMap<>();
            errors.put("msg","账户或密码错误");
            redirectAttributes.addFlashAttribute("errors",errors);
          return  "redirect:http://auth.gulimall.com";
        }else {
            MemberRespVo data = (MemberRespVo) r.getData("data", new TypeReference<MemberRespVo>() {
            });
            session.setAttribute("loginUser",data);
            return "redirect:http://gulimall.com";
        }
    }
    //社交登录
    @GetMapping("/sucess/getCode")
      public String getCode(@RequestParam("code") String code, HttpSession session) throws Exception {
        //参数封装
        String clientId="8f429b3772a493cd7549d4c316fa98e886521f9060955182cfcf9fc18a478045";
        String redirectUri="http://auth.gulimall.com/sucess/getCode";
        String clientSecret="4662cd2bcb5dd42537ce905e835e2cf1055f003ddb9941ce46ae83cd51bf0753";
        Map<String,String> header=new HashMap<>();
        Map<String,String> query=new HashMap<>();
        Map<String,String> map=new HashMap<>();
        map.put("client_id",clientId);
        map.put("redirect_uri",redirectUri);
        map.put("client_secret",clientSecret);
        map.put("grant_type","authorization_code");
        map.put("code",code);
        //业务处理，发送请求以code换取access_token
        HttpResponse response = HttpUtils.doPost("https://gitee.com", "/oauth/token", "post", header, query, map);
        //成功获取access_token后的处理
        if(response.getStatusLine().getStatusCode()==200)
        {
            //使用工具类进行信息的获取
            String json = EntityUtils.toString(response.getEntity());
            //获取之后定义一个类进行封装
            SocialUserVo userVo = JSONObject.parseObject(json,SocialUserVo.class);
            //通过access_token获取用户的id,用于辨识该gitee账户是否是第一次登录进该系统
            String accessToken = userVo.getAccessToken();
            Map<String,String> header1=new HashMap<>();
            Map<String,String> query1=new HashMap<>();
            query1.put("access_token",accessToken);
            //https://gitee.com/api/v5/user?access_token=3cca65262f61f15dfbde338dc1afde66
            HttpResponse responseUser = HttpUtils.doGet("https://gitee.com", "/api/v5/user", "get", header1, query1);
            String s = EntityUtils.toString(responseUser.getEntity());
            //获取到gitee的账户信息
            RealUserVo realUserVo = JSONObject.parseObject(s, RealUserVo.class);
            userVo.setName(realUserVo.getName());
            userVo.setUid(realUserVo.getId());
            //如果第一次登录成功，注册进数据库，通过id进行判断
            //如果不是第一次登录成功，登录即可，
            R r = registerFeignService.authLogin(userVo);
            if(r.getCode()==0)
            {
                MemberRespVo data = (MemberRespVo) r.getData(new TypeReference<MemberRespVo>() {
                });
                //此时将数据存入redis中
                session.setAttribute("loginUser",data);
                log.info("登录信息："+data.toString());
                return "redirect:http://gulimall.com";
            }else {
                return "redirect:http://auth.gulimall.com/login.html";
            }
        //否则对代码进行重定向
        }else {
            return "redirect:http://auth.gulimall.com/login.html";
        }

    }
    //对登录逻辑进行优化
    @GetMapping({"/","index.html","login.html"})
    public String loginPage(HttpSession session)
    {
        Object loginUser = session.getAttribute("loginUser");
        if(loginUser!=null){
            return "redirect:http://gulimall.com";
        }else {
            return "login";
        }
    }
    //退出逻辑
    @GetMapping("/logout")
    public String logout(HttpSession session, HttpServletRequest request){
        //用户的退出管理,删除session和相应的cookie
        session.removeAttribute("loginUser");
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if(cookie.getName().equals("GULIMALL-SESSION"))
            {
                cookie.setMaxAge(0);
            }
        }
        return  "redirect:http://gulimall.com";
    }
}
